gollvm: support installation targets
Add support for installing a build. The main install target of
interest is 'install-gollvm', which will install compiler, libgo, and
gotools.
Change-Id: I6aa050996f86332318338b6988668267675719b0
Reviewed-on: https://go-review.googlesource.com/112358
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6c25321..ccab33d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
include(CmakeUtils)
+include(AddGollvm)
# So that we can issue "make -jN" cmds in externalproject_add
processorcount(PROCESSOR_COUNT)
@@ -67,6 +68,10 @@
LOG_INSTALL 1
)
+# Top level targets for building, installing
+add_custom_target(gollvm ALL)
+add_custom_target(install-gollvm)
+
# In most use cases, we want to force a rebuild of all objects built
# from Go source if the compiler changes.
set(gocdep llvm-goc llvm-goc-token)
diff --git a/cmake/modules/AddGollvm.cmake b/cmake/modules/AddGollvm.cmake
new file mode 100644
index 0000000..954965c
--- /dev/null
+++ b/cmake/modules/AddGollvm.cmake
@@ -0,0 +1,66 @@
+
+# Library subdir within installation.
+# FIXME: select 32/64 based on default target triple
+set(libsubdir "lib64")
+
+# Set version number string (used by install rules)
+set(libversion ${LLVM_VERSION_MAJOR})
+if (NOT ${LLVM_VERSION_MINOR} EQUAL 0 AND NOT ${LLVM_VERSION_PATCH} EQUAL 0)
+ set(libversion "${libversion}.${LLVM_VERSION_MINOR}")
+endif()
+if (NOT ${LLVM_VERSION_PATCH} EQUAL 0)
+ set(libversion "${libversion}.${LLVM_VERSION_PATCH}")
+endif()
+
+# These are incorporated into GollvmConfig.h
+set(GOLLVM_LIBVERSION "${libversion}")
+set(GOLLVM_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
+set(GOLLVM_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${libsubdir}")
+
+macro(add_gollvm_library name)
+ llvm_add_library(${name} ${ARGN})
+
+ # Configure for install.
+ install(TARGETS ${name}
+ COMPONENT ${name}
+ LIBRARY DESTINATION ${libsubdir}
+ ARCHIVE DESTINATION ${libsubdir}
+ RUNTIME DESTINATION bin)
+
+ # Add an install target.
+ add_custom_target(install-${name}
+ DEPENDS ${name}
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=${name}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ add_dependencies(install-gollvm install-${name})
+
+ set_target_properties(${name} PROPERTIES FOLDER "Gollvm libraries")
+endmacro(add_gollvm_library)
+
+macro(add_gollvm_executable name)
+ add_llvm_executable(${name} ${ARGN} )
+ set_target_properties(${name} PROPERTIES FOLDER "Gollvm executables")
+endmacro(add_gollvm_executable)
+
+macro(add_gollvm_tool name)
+
+ add_gollvm_executable(${name} ${ARGN})
+
+ # Configure for install.
+ install(TARGETS ${name}
+ COMPONENT ${name}
+ LIBRARY DESTINATION ${libsubdir}
+ ARCHIVE DESTINATION ${libsubdir}
+ RUNTIME DESTINATION bin)
+
+ # Add an install target.
+ add_custom_target(install-${name}
+ DEPENDS ${name}
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=${name}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ add_dependencies(install-gollvm install-${name})
+
+ set_target_properties(${name} PROPERTIES FOLDER "Gollvm tools")
+endmacro()
diff --git a/cmake/modules/AutoGenGo.cmake b/cmake/modules/AutoGenGo.cmake
index ab5d51f..a93df0f 100644
--- a/cmake/modules/AutoGenGo.cmake
+++ b/cmake/modules/AutoGenGo.cmake
@@ -18,13 +18,14 @@
file(REMOVE ${outfile})
file(WRITE ${outfile} "package sys\n")
- # FIXME: normally DefaultGoRoot is set to the --prefix option used
- # when configuring (assuming that "configure" is run), but with
- # cmake it's possible to do a build first and then later on install
- # that build with a second run of cmake. For this reason looking at
- # things like CMAKE_INSTALL_PREFIX doesn't make much sense (it will
- # simply be set to /usr/local). This area needs some work.
- file(APPEND ${outfile} "func init() { DefaultGoroot = \"${bindir}\" }\n")
+ # FIXME: typical LLVM usage allows for performing a build without
+ # CMAKE_INSTALL_PREFIX set, then doing an install from the build
+ # using a newly chosen CMAKE_INSTALL_PREFIX value. This mode is
+ # not currently supported -- the install prefix has to be set properly
+ # as part of the original build.
+
+ # Tools subdir within the install.
+ file(APPEND ${outfile} "func init() { DefaultGoroot = \"${CMAKE_INSTALL_PREFIX}\" }\n")
# Compiler version
file(STRINGS "${srcroot}/../VERSION" rawver)
@@ -39,7 +40,7 @@
# executables. Where things like "cgo" will live hasn't been ironed
# out yet, so just pick a spot in the bin directory for now. See also
# 'DefaultGoRoot' above.
- file(APPEND ${outfile} "const GccgoToolDir = \"${bindir}\"\n")
+ file(APPEND ${outfile} "const GccgoToolDir = \"${CMAKE_INSTALL_PREFIX}/tools\"\n")
# FIXME: add a real switch base on configuration params here.
@@ -200,9 +201,7 @@
file(WRITE ${outfile} "package objabi\n\n")
file(APPEND ${outfile} "import \"runtime\"\n")
- # FIXME: see the comment in mkversion above relating to the GoRoot
- # setting (we may not know installation dir at time of cmake run).
- file(APPEND ${outfile} "func init() { defaultGOROOT = \"${binroot}\" }\n")
+ file(APPEND ${outfile} "func init() { defaultGOROOT = \"${GOLLVM_INSTALL_DIR}\" }\n")
file(APPEND ${outfile} "const defaultGO386 = `sse2`\n")
file(APPEND ${outfile} "const defaultGOARM = `5`\n")
@@ -245,7 +244,6 @@
#
# * package to use for generated Go code
# * output file to target
-# * path to gollvm driver binary
# * C compiler path
# * C++ compiler path
#
@@ -253,17 +251,15 @@
#
# EXPORT Generated public functions (ex: DefaultCC not defaultCC).
#
-function(mkzdefaultcc package outfile driverpath ccpath cxxpath)
+function(mkzdefaultcc package outfile ccpath cxxpath)
CMAKE_PARSE_ARGUMENTS(ARG "EXPORT" "" "" ${ARGN})
+ # Construct default driver path
+ set(driverpath "${GOLLVM_INSTALL_DIR}/bin/llvm-goc")
+
file(REMOVE ${outfile})
file(WRITE ${outfile} "package ${package}\n\n")
- # FIXME: once again, this is a problematic function since in theory
- # we don't yet know yet where things are going to be installed. For
- # the time being, just use that paths of the host build C/C++
- # compiler and the gollvm driver executable.
-
set(f1 "defaultGCCGO")
set(f2 "defaultCC")
set(f3 "defaultCXX")
diff --git a/cmake/modules/GoPackage.cmake b/cmake/modules/GoPackage.cmake
index c22a419..7e9e065 100644
--- a/cmake/modules/GoPackage.cmake
+++ b/cmake/modules/GoPackage.cmake
@@ -105,12 +105,27 @@
# Create target
add_custom_target(${pkgtarget} ALL DEPENDS ${pkg_outputs})
set_target_properties(${pkgtarget} PROPERTIES FOLDER "Object Libraries")
+ add_dependencies(gollvm ${pkgtarget})
# Caller needs to know these.
set(package_ofile ${package_ofile} PARENT_SCOPE)
set(package_picofile ${package_picofile} PARENT_SCOPE)
set(package_goxfile ${package_goxfile} PARENT_SCOPE)
- # TODO: add install rules
+ # *.gox files are installed in <lib>/go/<ver>/<triple>
+ set(goxinstalldest "lib${library_suffix}/go/${libversion}/${LLVM_DEFAULT_TARGET_TRIPLE}/${pdir}")
+
+ # Configure for install.
+ install(PROGRAMS ${package_goxfile}
+ COMPONENT ${pkgtarget}
+ DESTINATION ${goxinstalldest})
+
+ # Add an install target.
+ add_custom_target(install-${pkgtarget}
+ DEPENDS ${pkgtarget}
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=${pkgtarget}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ add_dependencies(install-gollvm install-${pkgtarget})
endfunction()
diff --git a/cmake/modules/GoProgram.cmake b/cmake/modules/GoProgram.cmake
index 98fa81f..c20fb77 100644
--- a/cmake/modules/GoProgram.cmake
+++ b/cmake/modules/GoProgram.cmake
@@ -20,9 +20,10 @@
# GOLIB Libraries to link against.
# GODEP Targets on which this program should be dependent.
# GOCFLAGS Additional arguments passed to Go compiler.
+# ISUBDIR Installation subdir (e.g. "tools" or "bin")
function(add_go_program progname target libgodir destdir)
- CMAKE_PARSE_ARGUMENTS(ARG "" "" "GOSRC;GOLIB;GODEP;GOCFLAGS" ${ARGN})
+ CMAKE_PARSE_ARGUMENTS(ARG "" "" "GOSRC;GOLIB;GODEP;GOCFLAGS;ISUBDIR" ${ARGN})
set(object "${progname}_.o")
@@ -38,7 +39,7 @@
OUTPUT ${object}
COMMAND "${gocompiler}" "-c" "-o" ${object} ${ARG_GOSRC} ${ARG_GOCFLAGS}
-I ${libgodir} -L ${libgodir}
- DEPENDS ${deps}
+ DEPENDS ${deps} ${gocdep}
COMMENT "Building object for go program ${progname}"
VERBATIM)
@@ -53,8 +54,20 @@
# Create target
add_custom_target(${target} ALL DEPENDS ${program_exe})
- set_target_properties(${target} PROPERTIES FOLDER "Tools")
- # TODO: add install rules
+ # Configure for install.
+ install(PROGRAMS ${program_exe}
+ COMPONENT ${target}
+ DESTINATION ${ARG_ISUBDIR})
+
+ # Add an install target.
+ add_custom_target(install-${target}
+ DEPENDS ${target}
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=${target}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ add_dependencies(install-gollvm install-${target})
+
+ set_target_properties(${target} PROPERTIES FOLDER "Gollvm gotools")
endfunction()
diff --git a/cmake/modules/GoVars.cmake b/cmake/modules/GoVars.cmake
index 4fa05a1..f6735cb 100644
--- a/cmake/modules/GoVars.cmake
+++ b/cmake/modules/GoVars.cmake
@@ -2,12 +2,14 @@
# Set goarch/goos based on what we see in the LLVM triple.
string(REGEX REPLACE "-" " " lht_components ${LLVM_DEFAULT_TARGET_TRIPLE})
separate_arguments(lht_components)
-list(GET lht_components 0 goarch)
+list(GET lht_components 0 llarch)
list(GET lht_components 2 goos)
# LLVM's "x86_64" is the same as Go's "amd64".
-if( ${goarch} STREQUAL "x86_64" )
+if( ${llarch} STREQUAL "x86_64" )
set(goarch "amd64")
+else()
+ message(SEND_ERROR "Arch ${llarch} not yet supported")
endif()
# List of all architectures, families, os flavors.
@@ -15,6 +17,13 @@
set(allgoarchfamily "I386" "ALPHA" "AMD64" "ARM" "ARM64" "IA64" "M68K" "MIPS" "MIPS64" "PPC" "PPC64" "S390" "S390X" "SPARC" "SPARC64")
set(allgoos "aix" "android" "darwin" "dragonfly" "freebsd" "irix" "linux" "netbsd" "openbsd" "plan9" "rtems" "solaris" "windows")
+# Set library suffix based on target triple
+if( ${llarch} STREQUAL "x86_64" )
+ set(library_suffix "64")
+else()
+ message(SEND_ERROR "Arch ${llarch} not yet supported")
+endif()
+
# FIXME: write code to insure that this is set and that the shell
# in question behaves properly.
set(shell $ENV{SHELL})
diff --git a/driver-main/CMakeLists.txt b/driver-main/CMakeLists.txt
index 9ac9449..685b5ac 100644
--- a/driver-main/CMakeLists.txt
+++ b/driver-main/CMakeLists.txt
@@ -30,7 +30,7 @@
include_directories(${EXTINSTALLDIR}/include)
# The llvm-goc executable itself
-add_llvm_tool(llvm-goc
+add_gollvm_tool(llvm-goc
llvm-goc.cpp)
# Record the fact that llvm-goc depends on these libs
@@ -60,3 +60,7 @@
# Token target.
add_custom_target(llvm-goc-token ALL DEPENDS ${llvm_goc_token})
+# Add a symlink to llvm-goc named "gccgo" in install dir, for
+# compatibility with gccgo.
+install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink \"llvm-goc\" \"${CMAKE_INSTALL_PREFIX}/bin/gccgo\")"
+ COMPONENT llvm-goc)
diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt
index d96d067..d1b13bd 100644
--- a/driver/CMakeLists.txt
+++ b/driver/CMakeLists.txt
@@ -7,6 +7,10 @@
tablegen(LLVM GollvmOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(GollvmDriverOptions)
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/GollvmConfig.h.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/GollvmConfig.h)
+
# Include directories needed for this lib.
include_directories(${GOFRONTEND_SOURCE_DIR})
include_directories(${BRIDGE_SOURCE_DIR})
diff --git a/driver/CompileGo.cpp b/driver/CompileGo.cpp
index c4bc427..2c0b094 100644
--- a/driver/CompileGo.cpp
+++ b/driver/CompileGo.cpp
@@ -1,4 +1,4 @@
-//===-- CompileGo.cpp ------------------------------------------------------===//
+//===-- CompileGo.cpp -----------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,6 +19,7 @@
#include "go-c.h"
#include "mpfr.h"
#include "GollvmOptions.h"
+#include "GollvmConfig.h"
#include "Action.h"
#include "Artifact.h"
@@ -29,6 +30,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IRPrintingPasses.h"
@@ -60,6 +62,8 @@
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include <sstream>
+
using namespace llvm;
namespace gollvm {
@@ -458,14 +462,27 @@
go_add_search_path(dir.c_str());
}
- // Library dirs
- // TODO: add version, architecture dirs
+ // Start with list of user-provided -L directories, then append an
+ // entry corresponing to the lib dir for the install.
std::vector<std::string> libargs =
args_.getAllArgValues(gollvm::options::OPT_L);
+ libargs.push_back(GOLLVM_INSTALL_LIBDIR);
+
+ // Populate Go package search path based on -L options.
for (auto &dir : libargs) {
- struct stat st;
- if (stat (dir.c_str(), &st) == 0 && S_ISDIR (st.st_mode))
- go_add_search_path(dir.c_str());
+ if (!sys::fs::is_directory(dir))
+ continue;
+
+ std::stringstream b1;
+ b1 << dir << sys::path::get_separator().str() << "go"
+ << sys::path::get_separator().str() << GOLLVM_LIBVERSION;
+ if (sys::fs::is_directory(b1.str()))
+ go_add_search_path(b1.str().c_str());
+
+ std::stringstream b2;
+ b2 << b1.str() << sys::path::get_separator().str() << triple_.str();
+ if (sys::fs::is_directory(b2.str()))
+ go_add_search_path(b2.str().c_str());
}
return true;
diff --git a/driver/GnuTools.cpp b/driver/GnuTools.cpp
index a3d669e..67d10ac 100644
--- a/driver/GnuTools.cpp
+++ b/driver/GnuTools.cpp
@@ -16,6 +16,7 @@
#include "Compilation.h"
#include "Driver.h"
#include "ToolChain.h"
+#include "GollvmConfig.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
@@ -302,7 +303,8 @@
}
// Pick up correct directory for Go libraries.
- std::string golib(llvm::Twine("-L" + compilation.driver().installDir() + "/../libgo/" + toolchain().driver().triple().str()).str());
+ std::string golib("-L");
+ golib += GOLLVM_INSTALL_LIBDIR;
cmdArgs.push_back(args.MakeArgString(golib.c_str()));
// Incorporate linker arguments needed for Go.
diff --git a/driver/GollvmConfig.h.cmake b/driver/GollvmConfig.h.cmake
new file mode 100644
index 0000000..bb0e56d
--- /dev/null
+++ b/driver/GollvmConfig.h.cmake
@@ -0,0 +1,17 @@
+
+#ifndef GOLLVM_CONFIG_H
+#define GOLLVM_CONFIG_H
+
+// Root of gollvm install
+#cmakedefine GOLLVM_INSTALL_DIR "@GOLLVM_INSTALL_DIR@"
+
+// Library subdir within install
+#cmakedefine GOLLVM_INSTALL_LIBDIR "@GOLLVM_INSTALL_LIBDIR@"
+
+// Library version (e.g. 7, 4.5, 8.0.1)
+#cmakedefine GOLLVM_LIBVERSION "@GOLLVM_LIBVERSION@"
+
+// Compiler version. Same as library version currently.
+#define GOLLVM_COMPILERVERSION GOLLVM_LIBVERSION
+
+#endif // GOLLVM_CONFIG_H
diff --git a/gotools/CMakeLists.txt b/gotools/CMakeLists.txt
index ad655dc..efeb26c 100644
--- a/gotools/CMakeLists.txt
+++ b/gotools/CMakeLists.txt
@@ -27,7 +27,7 @@
# Cgo needs a copy of the defaultCC function in the "main" package.
set(cgozdefaultccdotgo "${gotools_binroot}/zdefaultcc.go")
set(cgozdefaultcctmp "${gotools_binroot}/zdefaultcc.go.tmp")
-mkzdefaultcc("main" ${cgozdefaultcctmp} ${gollvm_driver}
+mkzdefaultcc("main" ${cgozdefaultcctmp}
${CMAKE_C_COMPILER} ${CMAKE_CXX_COMPILER})
copy_if_different(${cgozdefaultcctmp} ${cgozdefaultccdotgo})
@@ -73,17 +73,24 @@
list(APPEND toolfiles "${${tool}_extra_go_files}")
endif()
+ set(isubdir "tools")
+ if("${tool}" STREQUAL "go")
+ set(isubdir "bin")
+ endif()
+
# Create target for program.
add_go_program(${tool} ${tool_target}
${libgo_binroot} ${gotools_binroot}
GOSRC ${toolfiles}
GOLIB ${libgotool_archive}
+ ISUBDIR ${isubdir}
GODEP libgotool libgo_shared libgo_static)
list(APPEND allgotools ${tool_target})
endif()
endforeach()
add_custom_target(gotools_all DEPENDS ${allgotools})
+add_dependencies(gollvm gotools_all)
message(STATUS "gotools: generating check targets")
diff --git a/libgo/CMakeLists.txt b/libgo/CMakeLists.txt
index 83ee5df..4584503 100644
--- a/libgo/CMakeLists.txt
+++ b/libgo/CMakeLists.txt
@@ -222,7 +222,7 @@
# Rules for zdefaultcc.go
set(zdefaultccdotgo "${libgo_binroot}/zdefaultcc.go")
set(zdefaultcctmp "${libgo_binroot}/zdefaultcc.go.tmp")
-mkzdefaultcc("cfg" ${zdefaultcctmp} ${gollvm_driver}
+mkzdefaultcc("cfg" ${zdefaultcctmp}
${CMAKE_C_COMPILER} ${CMAKE_CXX_COMPILER} EXPORT)
copy_if_different(${zdefaultcctmp} ${zdefaultccdotgo})
@@ -456,7 +456,7 @@
add_dependencies(libgo_c_nonpiclib runtimeinctarg)
# Static libgo -- combines non-pic C objects and non-pic Go objects
-add_library(libgo_static STATIC
+add_gollvm_library(libgo_static STATIC
$<TARGET_OBJECTS:libgo_c_nonpiclib>
${libgo_go_nonpicobjects}
$<TARGET_OBJECTS:libbacktrace_nonpiclib>
@@ -470,7 +470,7 @@
"${CMAKE_SHARED_LINKER_FLAGS}")
# Shared libgo -- combines pic C objects and non-pic Go objects.
-add_library(libgo_shared SHARED
+add_gollvm_library(libgo_shared SHARED
$<TARGET_OBJECTS:libgo_c_piclib>
${libgo_go_picobjects}
$<TARGET_OBJECTS:libbacktrace_piclib>
@@ -484,7 +484,7 @@
set(libgobegincfiles
"${libgo_csrcroot}/runtime/go-main.c")
# libgobegin.a (static library only)
-add_library(libgobegin STATIC
+add_gollvm_library(libgobegin STATIC
${libgobegincfiles})
add_dependencies(libgobegin runtimeinctarg)
target_include_directories(libgobegin PUBLIC
@@ -500,7 +500,7 @@
set(libgolibbegincfiles
"${libgo_csrcroot}/runtime/go-libmain.c")
# libgolibbegin.a (static library only)
-add_library(libgolibbegin STATIC
+add_gollvm_library(libgolibbegin STATIC
${libgolibbegincfiles})
add_dependencies(libgolibbegin runtimeinctarg)
target_include_directories(libgolibbegin PUBLIC
@@ -516,6 +516,7 @@
# Pseudo-target for all libgo buildables.
add_custom_target(libgo_all DEPENDS
llvm-goc libgo_static libgo_shared libgobegin libgolibbegin)
+add_dependencies(gollvm libgo_all)
# Create a target-specific symlink to the Go library dir. This is
# an interim solution; ideally we want to key off of CMAKE_INSTALL_PREFIX.