Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 29 additions & 42 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,13 @@ def run(args):
''')
return 0

## Process argument and setup the compiler
state = EmccState(args)
options, newargs = phase_parse_arguments(state)

if not shared.SKIP_SUBPROCS:
shared.check_sanity()

if '--version' in args:
print(version_string())
print('''\
Expand Down Expand Up @@ -566,13 +573,6 @@ def run(args):
print(shared.shlex_join(parts[1:]))
return 0

## Process argument and setup the compiler
state = EmccState(args)
options, newargs = phase_parse_arguments(state)

if not shared.SKIP_SUBPROCS:
shared.check_sanity()

if 'EMMAKEN_NO_SDK' in os.environ:
exit_with_error('EMMAKEN_NO_SDK is no longer supported. The standard -nostdlib and -nostdinc flags should be used instead')

Expand Down Expand Up @@ -618,9 +618,6 @@ def run(args):
print(libname)
return 0

if not input_files and not state.link_flags:
exit_with_error('no input files')

if options.reproduce:
create_reproduce_file(options.reproduce, args)

Expand All @@ -641,8 +638,6 @@ def run(args):
return link.run(linker_inputs, options, state, newargs)
else:
logger.debug('stopping after compile phase')
for flag in state.link_flags:
diagnostics.warning('unused-command-line-argument', "argument unused during compilation: '%s'" % flag[1])
return 0


Expand Down Expand Up @@ -670,9 +665,9 @@ def phase_parse_arguments(state):
newargs = diagnostics.capture_warnings(newargs)

for i in range(len(newargs)):
if newargs[i] in ('-l', '-L', '-I'):
# Scan for individual -l/-L/-I arguments and concatenate the next arg on
# if there is no suffix
if newargs[i] in ('-l', '-L', '-I', '-z'):
# Scan for flags that can be written as either one or two arguments
# and normalize them to the single argument form.
newargs[i] += newargs[i + 1]
newargs[i + 1] = ''

Expand Down Expand Up @@ -764,33 +759,24 @@ def phase_setup(options, state, newargs):
input_files.append((i, arg))
elif arg.startswith('-L'):
state.add_link_flag(i, arg)
newargs[i] = ''
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

trying to understand what this part of the change is for...
previously we were removing the flag from the list and now aren't, so that it gets passed through to clang and clang can warn?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes exactly. If we simply allow all these flags to pass through to clang then clang can take care of issuing the warning instead of us. . which simplifies the code and paves that way for os.execv to be used.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ok thanks, can you put something to that effect in the commit message?

elif arg.startswith('-l'):
state.add_link_flag(i, arg)
newargs[i] = ''
elif arg == '-z':
state.add_link_flag(i, newargs[i])
state.add_link_flag(i + 1, newargs[i + 1])
newargs[i] = ''
newargs[i + 1] = ''
elif arg.startswith('-z'):
state.add_link_flag(i, newargs[i])
newargs[i] = ''
elif arg.startswith('-Wl,'):
# Multiple comma separated link flags can be specified. Create fake
# fractional indices for these: -Wl,a,b,c,d at index 4 becomes:
# (4, a), (4.25, b), (4.5, c), (4.75, d)
link_flags_to_add = arg.split(',')[1:]
for flag_index, flag in enumerate(link_flags_to_add):
state.add_link_flag(i + float(flag_index) / len(link_flags_to_add), flag)
newargs[i] = ''
elif arg == '-Xlinker':
state.add_link_flag(i + 1, newargs[i + 1])
newargs[i] = ''
newargs[i + 1] = ''
elif arg == '-s':
state.add_link_flag(i, newargs[i])
newargs[i] = ''
elif arg == '-':
input_files.append((i, arg))
newargs[i] = ''
Expand Down Expand Up @@ -950,11 +936,6 @@ def get_clang_output_extension(state):

@ToolchainProfiler.profile_block('compile inputs')
def phase_compile_inputs(options, state, newargs, input_files):
def is_link_flag(flag):
if flag in ('-nostdlib', '-nostartfiles', '-nolibc', '-nodefaultlibs'):
return True
return flag.startswith(('-l', '-L', '-Wl,'))

if shared.run_via_emxx:
compiler = [shared.CLANG_CXX]
else:
Expand All @@ -964,7 +945,7 @@ def is_link_flag(flag):
logger.debug('using compiler wrapper: %s', config.COMPILER_WRAPPER)
compiler.insert(0, config.COMPILER_WRAPPER)

compile_args = [a for a in newargs if a and not is_link_flag(a)]
compile_args = newargs
system_libs.ensure_sysroot()

def get_language_mode(args):
Expand Down Expand Up @@ -1002,7 +983,7 @@ def get_clang_command_asm():
# with -MF! (clang seems to not recognize it)
logger.debug(('just preprocessor ' if state.has_dash_E else 'just dependencies: ') + ' '.join(cmd))
shared.check_call(cmd)
return []
sys.exit(0)

# Precompiled headers support
if state.mode == Mode.PCH:
Expand All @@ -1015,7 +996,7 @@ def get_clang_command_asm():
cmd += ['-o', options.output_file]
logger.debug(f"running (for precompiled headers): {cmd[0]} {' '.join(cmd[1:])}")
shared.check_call(cmd)
return []
sys.exit(0)

if state.mode == Mode.COMPILE_ONLY:
inputs = [i[1] for i in input_files]
Expand All @@ -1027,18 +1008,24 @@ def get_clang_command_asm():
cmd += ['-o', options.output_file]
if get_file_suffix(options.output_file) == '.bc' and not settings.LTO and '-emit-llvm' not in state.orig_args:
diagnostics.warning('emcc', '.bc output file suffix used without -flto or -emit-llvm. Consider using .o extension since emcc will output an object file, not a bitcode file')
ext = get_clang_output_extension(state)
shared.check_call(cmd)
if not options.output_file:
# Rename object files to match --default-obj-ext
# TODO: Remove '--default-obj-ext' to reduce this complexity
ext = get_clang_output_extension(state)
if options.default_object_extension != ext:
for i in inputs:
output = unsuffixed_basename(i) + ext
new_output = unsuffixed_basename(i) + options.default_object_extension
shutil.move(output, new_output)
return []
if not options.output_file and options.default_object_extension != ext:
for i in inputs:
output = unsuffixed_basename(i) + ext
new_output = unsuffixed_basename(i) + options.default_object_extension
shutil.move(output, new_output)
sys.exit(0)

# In COMPILE_AND_LINK we need to compile source files too, but we also need to
# filter out the link flags

def is_link_flag(flag):
if flag in ('-nostdlib', '-nostartfiles', '-nolibc', '-nodefaultlibs', '-s'):
return True
return flag.startswith(('-l', '-L', '-Wl,', '-z'))

compile_args = [a for a in compile_args if a and not is_link_flag(a)]
linker_inputs = []
seen_names = {}

Expand Down
6 changes: 5 additions & 1 deletion test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -11458,7 +11458,7 @@ def test_linker_flags_pass_through(self):

def test_linker_flags_unused(self):
err = self.run_process([EMXX, test_file('hello_world.cpp'), '-c', '-lbar'], stderr=PIPE).stderr
self.assertContained("warning: argument unused during compilation: '-lbar' [-Wunused-command-line-argument]", err)
self.assertContained("warning: -lbar: 'linker' input unused [-Wunused-command-line-argument]", err)

def test_linker_input_unused(self):
self.run_process([EMXX, '-c', test_file('hello_world.cpp')])
Expand Down Expand Up @@ -14279,3 +14279,7 @@ def test_strndup(self):

def test_errar(self):
self.do_other_test('test_errar.c')

def test_no_input_files(self):
err = self.expect_fail([EMCC, '-c'])
self.assertContained('clang: error: no input files', err)
6 changes: 4 additions & 2 deletions test/test_sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,13 @@ def do(self, command, env=None):
def check_working(self, command, expected=None):
if type(command) is not list:
command = [command]
if command == [EMCC]:
command = [EMCC, '--version']
if expected is None:
if command[0] == EMCC or (len(command) >= 2 and command[1] == EMCC):
expected = 'no input files'
expected = 'emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld)'
else:
expected = "could not find the following tests: blahblah"
expected = 'could not find the following tests: blahblah'

output = self.do(command)
self.assertContained(expected, output)
Expand Down