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

Fortran support #998

Closed
arjo129 opened this issue Mar 26, 2013 · 8 comments
Closed

Fortran support #998

arjo129 opened this issue Mar 26, 2013 · 8 comments
Labels

Comments

@arjo129
Copy link

arjo129 commented Mar 26, 2013

Recently I tried to build GNU octave through emscripten, however it failed because of parts written in Fortran. may

be it would be possible to add fortran, as I understand currently emscripten is translating llvm bytecode to javascript. And in extension, one could add Ada and Obj-C support?

@kripken
Copy link
Member

kripken commented Mar 31, 2013

In principle yes. Search the issues and mailing list, I think some of these have work on them done already.

@jandoerntlein
Copy link

Here is what I did to enable Fortran support in Emscripten:

  • installed DraggonEgg plugin for gfortran (dragonegg.llvm.org)
  • introduced SHARED.DRAGONEGG with a path to dragonegg.so in the .emscripten config file
    DRAGONEGG = os.path.expanduser('/usr/lib/gcc/x86_64-linux-gnu/4.6/plugin/dragonegg.so')
  • For the sake of clarity added "emfortran" (like em++) as a script for Fortan files
  • in the toolchain cmake/Platform/Emscripten.cmake, add "emfortran" as a compiler
(...)
if ("${CMAKE_C_COMPILER}" STREQUAL "")
    set(CMAKE_C_COMPILER "${EMSCRIPTEN_ROOT_PATH}/emcc${EMCC_SUFFIX}")
endif()
if ("${CMAKE_CXX_COMPILER}" STREQUAL "")
    set(CMAKE_CXX_COMPILER "${EMSCRIPTEN_ROOT_PATH}/em++${EMCC_SUFFIX}")
endif()
if ("${CMAKE_Fortran_COMPILER}" STREQUAL "")
    set(CMAKE_Fortran_COMPILER "${EMSCRIPTEN_ROOT_PATH}/emfortran${EMCC_SUFFIX}") # use our new script
endif()
(...)
include(CMakeForceCompiler)
CMAKE_FORCE_C_COMPILER("${CMAKE_C_COMPILER}" Clang)
CMAKE_FORCE_CXX_COMPILER("${CMAKE_CXX_COMPILER}" Clang)
CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" gfortran) # use gfortran with dragonegg
(...)
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELEASE")
set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_MINSIZEREL")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELWITHDEBINFO")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELEASE")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_MINSIZEREL")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELWITHDEBINFO")
set(CMAKE_Fortran_LINK_EXECUTABLE "") # don't link anything
(...)
  • finally edited "emcc" to parse Fortran files as well and added functionality to use gfortran and dragonegg
FORTRAN_ENDINGS = ('.f', '.F') # define the endings to identify a Fortran source file
CXX_SUFFIXES = ('.cpp', '.cxx', '.cc')
SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm', '.f', '.FF') # accept .f and .FF files
  • here is the major change to emcc:
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
  for input_file in input_files:
    file_suffix = filename_type_suffix(input_file)
    if file_suffix.endswith(SOURCE_SUFFIXES):
      logging.debug('compiling source file: ' + input_file)
      input_file = shared.Building.preprocess(input_file, in_temp(uniquename(input_file)))
      output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
      temp_files.append(output_file)
      fortran_llvm = in_temp(unsuffixed(uniquename(input_file)) + '.ll')
      if file_suffix.endswith(FORTRAN_ENDINGS): # create .ll (bitcode) file from .f (Fortran) files
        call    = 'gfortran'
        args    = [input_file, '-flto', '-S', '-m32', '-fplugin='+shared.DRAGONEGG, '-O2', '-o', fortran_llvm] # use the DRAGONEGG variable from the .emscripten config file
      else: 
        args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
        if file_suffix.endswith(CXX_SUFFIXES):
          args += shared.EMSDK_CXX_OPTS
      logging.debug("running: " + call + ' ' + ' '.join(args))
      execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
      if file_suffix.endswith(FORTRAN_ENDINGS):
        shared.Building.llvm_as(fortran_llvm, output_file) # create .o file from .ll
      if not os.path.exists(output_file):
        logging.error('compiler frontend failed to generate LLVM bitcode, halting')
        sys.exit(1)
    else: # bitcode
        (...)

I know that this patch is a very hacky one. It would be great if someone could present a similiar solution that can be merged into the official repo!

@juj juj added the CMake label Jul 28, 2014
@gagern
Copy link
Contributor

gagern commented Jun 11, 2015

I've been using a similar workaround today (in an attempt to compile LAPACK), except I've used a shell script instead of Python code to run gfortran and llvm-as. And I did so without intermediate file, using a stdout to stdin pipeline instead.

I get warnings that the bytecode of the Fortran files is from a different triple than what emcc compils from C. So I guess one would have to compile Dragonegg against the LLVM version of emscripten. Not sure (yet) how to do that.

If I feed a Fortran file to my native clang it compiles that all right. I don't know how it does that, whether it's calling gfortran or gcc behind the scenes, and if so, whether it relies on Dragonegg. I also don't know where that capability gets configured, how to enable that for the emscripten build of LLCM and clang.

Once Fortran can be compiled, we should investigate ways to compile libgfortran as well, to offer a suitable runtime environment. But Fortran sources first.

Search the issues and mailing list, I think some of these have work on them done already.

Some pointers:

@jandoerntlein
Copy link

I get warnings that the bytecode of the Fortran files is from a different triple than what emcc compils from C. So I guess one would have to compile Dragonegg against the LLVM version of emscripten. Not sure (yet) how to do that.

I believe you can safely ignore that as long as you make sure that the target architecture (like x86, x64 etc) matches. But still it would be nice to fix this :)

@jakirkham
Copy link

Related to issue ( #5553 ).

@stale
Copy link

stale bot commented Sep 18, 2019

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 7 days. Feel free to re-open at any time if this issue is still relevant.

@stale stale bot added the wontfix label Sep 18, 2019
@jakirkham
Copy link

Yeah I guess this or #5553 should be closed and marked as a duplicate.

@stale stale bot removed the wontfix label Sep 19, 2019
@sbc100
Copy link
Collaborator

sbc100 commented Sep 19, 2019

Closing as a duplicate.

@sbc100 sbc100 closed this as completed Sep 19, 2019
axodox pushed a commit to axodox/emscripten that referenced this issue Mar 18, 2023
…e#998)

This is needed to allow custom rules and/or transitions on top of wasm_cc_binary (e.g. to workaround emscripten-core#972).

It's debatable whether .wasm is the correct executable target for non-standalone Wasm builds, but we don't have a way to differentiate those in wasm_cc_binary, and considering that this attribute isn't exported now, it shouldn't break anything.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants