Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse all command line options in repl.c #9482

Merged
merged 1 commit into from
Feb 21, 2015
Merged

Parse all command line options in repl.c #9482

merged 1 commit into from
Feb 21, 2015

Conversation

jakebolewski
Copy link
Member

Addresses #9384. Currently the options that are not in jl_compileropts_t are stored into a new jl_options_t struct. This struct is then loaded when processing the command line options in base/client.jl. This PR adds some sanity check tests for command line arguments as well.

I think it would be better to rename jl_compileropts_t and just have one option struct for all command line arguments (and api to query the arguments from Julia).

I've deprecated --no-history-file and --no-startup flags in favor of --history-file={yes|no} and --startup-file={yes|no} so all command line options have a similar structure.

@tkelman
Copy link
Contributor

tkelman commented Dec 29, 2014

While you're at it, documentation of these is duplicated across several different places, doc/manual/getting-started.rst and doc/man/julia.1 and possibly others, all of which have fallen out of date.

@vtjnash
Copy link
Member

vtjnash commented Dec 29, 2014

this seems good. +1

one thing to be aware of is that some of the arguments, such as -F, -E and -n, previously had immediate effect when encountered, and thus could be repeated

@jakebolewski
Copy link
Member Author

@vtjnash good point, I couldn't replicate all previous behavior with how command line options were processed so it would be useful if others test this out to see if I broke something.

@samoconnor
Copy link
Contributor

Nice one.
It was confusing for me to try to find how the "-e" option was handled because it was not in repl.c.
See #9468 and specifically: https://github.com/samoconnor/julia/blame/doc_notes_branch/doc/devdocs/init.rst#L22

@jakebolewski jakebolewski force-pushed the jcb/fixcopts branch 3 times, most recently from 59a8448 to 8301aa6 Compare January 5, 2015 03:44
@jakebolewski
Copy link
Member Author

Rebased and squashed. I consolidated all options into a single struct as talked about. The old jl_compileropts struct was exported so I'm unsure if we consider this part of the "public" C API. On the julia side, the option struct now lives in base/options.jl. I also added more tests and updated the documentation.

@jakebolewski jakebolewski changed the title WIP: Parse all command line options in repl.c Parse all command line options in repl.c Jan 5, 2015
@jakebolewski
Copy link
Member Author

The tests on Windows should pass now.


-O, --optimize
Run time-intensive code optimizations
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the separate line here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, maybe I found it easier to read at the time?

@tkelman
Copy link
Contributor

tkelman commented Jan 6, 2015

Needs a rebase already?


void parse_opts(int *argcp, char ***argvp)
{
static char* shortopts = "+H:hJ:C:O";
enum { machinefile = 300,
color,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no tabs whenever you rebase this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks. I have to change my Vim defaults.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that #9732 might get merged before this and touches the same code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that, @jakebolewski.

@jakebolewski jakebolewski force-pushed the jcb/fixcopts branch 3 times, most recently from 072b017 to 31d683d Compare January 13, 2015 23:18
@jakebolewski
Copy link
Member Author

Ok, I rebased just rebased. It needs some review as it touches a lot of code and I'm unsure if shoving everything into one struct is the cleanest way to do this.

global process_options
function process_options(opts::JLOptions, args::Vector{UTF8String})
if !isempty(args) && (arg = first(args); arg[1] == '-' && in(arg, reqarg))
println(STDERR, "julia: option `$arg` is missing an argument")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couldn't we do this by checking the return value of getopt_long? http://man7.org/linux/man-pages/man3/getopt.3.html#RETURN_VALUE

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be possible if the long option struct array was an exported global.

@ihnorton
Copy link
Member

aesthetics (ignore, more or less)

  • looks_like(deity_obj) && smells_like(deity_obj) == true
  • at very least, having something called eval in there feels weird

other than my one inline comment, the actual code LGTM. lots of repetition but i guess that is unavoidable here. it would be nice if we could store all of the text-based/non-hot longopts in a dictionary, but i guess that would be harder to use (or not available at all when needed) from some parts of the C code.

@ihnorton
Copy link
Member

Bump

@tkelman
Copy link
Contributor

tkelman commented Feb 12, 2015

#9468, #9450, or both?

@jakebolewski
Copy link
Member Author

9450, he has been rebasing it too many times I don't want to add to his pain :-)

@JeffBezanson
Copy link
Member

9450 merged.

@StefanKarpinski
Copy link
Member

See also #10226 – argument parsing should stop at --.

@jakebolewski
Copy link
Member Author

The c library that we use for unix opt parsing, ui/getopt.c would have to be changed to support this.

@StefanKarpinski
Copy link
Member

How feasible is just moving all of the option parsing into Julia? Most of the REPL is in Julia these days so it seems like it shouldn't be too crazy to do that.

@jakebolewski
Copy link
Member Author

I don't think too feasible at the moment. How do you turn off boundschecking for generated julia code that is being executed to parse the option to turn off boundschecking?

@tkelman
Copy link
Contributor

tkelman commented Feb 17, 2015

Moving things to Julia is the opposite direction from what this PR does. And there's a bootstrapping problem for the flags that control compiler options, which is a good chunk of them.

Note that we use the system version of getopt everywhere except in the (currently broken) MSVC build.

@samoconnor
Copy link
Contributor

@tkelman says that system getopt is used by default.
Double dash end of args should already be handled by the system getopt:

Linux: The special argument "--" forces an end of option-scanning regardless of the scanning mode
BSD: The interpretation of options in the argument list may be cancelled by
the option `--' (double dash) which causes getopt() to signal the end of
argument processing and return -1.

Is there an overall policy for how cross-platform issue should be handled in Julia?

e.g. my usual rules for a non-GUI cross-platform system would be:

  • Use POSIX-ish APIs
  • Use GNU extensions, BSD extensions, etc wherever these have been adopted by the important platforms (i.e. Linux and OSX)
  • Disallow #ifdef WIN32 in the main codebase
  • Support windows by by linking to a compatibility library that provides whatever POSIX-ish functions are missing on windows (e.g. ui/getopt.c and there are lots of implementation of posix functions for windows out there...)
  • Allow building against cygwin as an alternative.

The alternatives are:

  • Code full of #ifdef WIN32
  • Only supporting the smallest common subset of OS-librarty features
  • Building yet-another-cross-platform-API-wrapper-layer-library-thingamabob.

@tkelman
Copy link
Contributor

tkelman commented Feb 17, 2015

@samoconnor everything you describe is what we use libuv for...

@samoconnor
Copy link
Contributor

True, libuv is used (and seems like a decent choice) for network and IO stuff, but there is still a lot of #ifdef OS_WINDOWS elsewhere.

find julia/src/ -name '*.c' | xargs grep -l OS_WINDOWS | wc -l
26

@tkelman
Copy link
Contributor

tkelman commented Feb 18, 2015

Well going out of your way to have fewer ifdefs if you don't deem Windows an "important platform" is an option for some projects. Cygwin is not an option for Julia since Cygwin doesn't implement any asynchronous IO required by libuv.

For things that libuv doesn't cover, like a different set of headers being available, libc functions like strtod having different functionality, handling of paths and executables and shared libraries and exception handling and debug info and calling conventions (and and and) being different, etc, they're handled on a case-by-case basis. I don't think there's one unifying policy, other than things mostly work now, and we like making them work better where possible. Refactorings that clean things up are also welcome when they don't harm existing functionality.

@samoconnor
Copy link
Contributor

@tkelman ... that all sounds reasonable.
But, I think something being an "important platform" is an emotive way to think about it.
I think you can have windows be an "important platform" while simultaneously saying "libuv + POSIX(-ish) is the primary OS API layer, and windows specific implementations are hidden behind that". The former is a matter of marketing and customer support, the latter is a matter of architectural discipline and maintainability.

I think that it's important to have clear rules on which layers are allowed to talk to which other layers.
One man's quick fix for platform-xyz becomes another mans refactoring nightmare later on...

(apologies to @jakebolewski for going so far off topic on your P.R.)

@tkelman
Copy link
Contributor

tkelman commented Feb 18, 2015

We'd actually rather remove our posix assumptions as much as possible. Ideally libuv should stand between us and either posix or win32 for as much as it can. There are plenty of places that it can't do the job completely though, and llvm doesn't abstract away the OS to the extent that would allow us to clean up codegen, debuginfo, ffi, etc. The new ORC JIT API's that are being worked on in 3.7 might be nicer in this respect, I'm not sure?

I did some quick comparisons and we have fewer Windows ifdefs than cmake or CPython, but evidently a bit more than either LLVM or luajit (or I was just searching for the wrong defines in those projects). Julia's C core is pretty small by language implementation standards, but it tends to be grouped by functionality rather than having centralized platform differences consolidated into a handful of headers or source files.

@vtjnash
Copy link
Member

vtjnash commented Feb 18, 2015

I believe that LLVM separates a lot of it's host specific code into separate files (including autogenerated tblgen #include files), so that fewer ifdef's can cover more code.

I don't really care how many ifdef's are needed for the C code. My goal is to largely eliminate the need for them in user code inside of Julia, by providing a user interface that can be consistently implemented across platform. this effort is greatly assisted by libuv, since it provides a consistent interface for dealing with a variety of platform-specific issues (generally related to I/O).

 - consolidate all compiler / cmdline options into jl_options_t struct in julia.h

 - add options.jl to base/ with an immutable type JLOptions that
   reflects the jl_options_t struct

 - add --procs=<n> command line flag (equivalent to -p <n>)

 - add --history-file={yes|no} and --startup-file={yes|no} cmdline opts

 - --worker command line arguments changed to --worker,
   --worker=default, or --worker=custom

 - deprecate -f, -F, --no-startup, --no-history-file cmdline flags

 - add tests for cmdline arguments in test/cmdlineargs.jl

 - modify test/Makefile and tests to use long command line option,
   add command line argument tests to runtests.jl

 - update relevant docs in the manual and manpages
@jakebolewski
Copy link
Member Author

Ok, rebased.

@amitmurthy I had to change --worker custom to --worker=custom (--worker is the same as --worker=default) reflecting recent changes to the cluster manager interface.

jakebolewski added a commit that referenced this pull request Feb 21, 2015
Parse all command line options in repl.c
@jakebolewski jakebolewski merged commit 6051af5 into master Feb 21, 2015
@jakebolewski jakebolewski deleted the jcb/fixcopts branch February 21, 2015 21:09
@amitmurthy
Copy link
Contributor

OK. Nice work on the cleanup.

startup = false
end
# load ~/.julia_history file
no_history_file = bool(opts.historyfile)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a ! here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched this to history_file=true/false which follows other changes in this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants