2016-01-26 20:14:33 -06:00
#!/usr/bin/perl -w
2016-08-14 16:22:25 +05:30
# Need perl > 5.10 to use logic-defined or
use 5.006 ; use v5 .10 .1 ;
2016-01-26 20:14:33 -06:00
use File::Basename ;
2016-07-13 11:26:03 +05:30
# HIP compiler driver
2016-01-26 20:14:33 -06:00
# Will call NVCC or HCC (depending on target) and pass the appropriate include and library options for
# the target compiler and HIP infrastructure.
# Will pass-through options to the target compiler. The tools calling HIPCC must ensure the compiler
# options are appropriate for the target compiler.
# Environment variable HIP_PLATFORM control compilation path:
# HIP_PLATFORM='nvcc' or HIP_PLATFORM='hcc'.
# If HIP_PLATFORM is not set hipcc will attempt auto-detect based on if nvcc is found.
#
# Other environment variable controls:
2016-07-13 11:26:03 +05:30
# HIP_PATH : Path to HIP directory, default is one dir level above location of this script
2016-01-26 20:14:33 -06:00
# CUDA_PATH : Path to CUDA SDK (default /usr/local/cuda). Used on NVIDIA platforms only.
2016-04-15 12:56:31 +05:30
# HCC_HOME : Path to HCC SDK (default /opt/rocm/hcc). Used on AMD platforms only.
# HSA_PATH : Path to HSA dir (default /opt/rocm/hsa). Used on AMD platforms only.
2016-01-26 20:14:33 -06:00
2016-02-26 13:47:58 -06:00
if ( scalar @ ARGV == 0 ) {
print "No Arguments passed, exiting ...\n" ;
exit ( - 1 ) ;
}
2016-01-26 20:14:33 -06:00
2016-08-14 16:22:25 +05:30
#---
# Function to parse config file
sub parse_config_file {
my ( $ file , $ config ) = @ _ ;
if ( open ( CONFIG , "$file" ) ) {
while ( <CONFIG> ) {
my $ config_line = $ _ ;
chop ( $ config_line ) ;
$ config_line =~ s/^\s*// ;
$ config_line =~ s/\s*$// ;
if ( ( $ config_line !~ /^#/ ) && ( $ config_line ne "" ) ) {
my ( $ name , $ value ) = split ( /=/ , $ config_line ) ;
$$ config { $ name } = $ value ;
}
}
close ( CONFIG ) ;
}
}
$ verbose = $ ENV { 'HIPCC_VERBOSE' } // 0 ;
2016-03-24 13:33:07 -05:00
# Verbose: 0x1=commands, 0x2=paths, 0x4=hippc args
2016-01-26 20:14:33 -06:00
2016-08-14 16:22:25 +05:30
$ HIP_PATH = $ ENV { 'HIP_PATH' } // dirname ( dirname $ 0 ) ; # use parent directory of hipcc
2016-01-26 20:14:33 -06:00
2016-08-03 12:01:48 +05:30
#---
2016-08-14 16:22:25 +05:30
# Read .buildInfo
2016-08-03 12:01:48 +05:30
my % hipConfig = ( ) ;
2016-08-14 16:22:25 +05:30
parse_config_file ( "$HIP_PATH/lib/.buildInfo" , \ % hipConfig ) ;
2016-08-03 12:01:48 +05:30
2016-01-26 20:14:33 -06:00
#---
#HIP_PLATFORM controls whether to use NVCC or HCC for compilation:
2016-08-14 16:22:25 +05:30
$ HIP_PLATFORM = `$HIP_PATH/bin/hipconfig --platform` // "hcc" ;
2016-07-11 16:38:41 +05:30
$ HIP_VERSION = `$HIP_PATH/bin/hipconfig --version` ;
2016-05-02 11:33:22 -05:00
2016-01-26 20:14:33 -06:00
if ( $ verbose & 0x2 ) {
2016-07-13 11:26:03 +05:30
print ( "HIP_PATH=$HIP_PATH\n" ) ;
print ( "HIP_PLATFORM=$HIP_PLATFORM\n" ) ;
2016-01-26 20:14:33 -06:00
}
2016-04-28 13:17:49 -05:00
# set if user explicitly requests -stdlib=libc++. (else we default to libstdc++ for better interop with g++):
2016-05-02 23:47:04 -05:00
$ setStdLib = 0 ; # TODO - set to 0
2016-01-26 20:14:33 -06:00
if ( $ HIP_PLATFORM eq "hcc" ) {
2016-08-14 16:22:25 +05:30
$ HSA_PATH = $ ENV { 'HSA_PATH' } // "/opt/rocm/hsa" ;
$ HCC_HOME = $ ENV { 'HCC_HOME' } // $ hipConfig { 'HCC_HOME' } // "/opt/rocm/hcc" ;
2016-08-11 16:13:44 -05:00
$ HCC_VERSION = `${HCC_HOME}/bin/hcc --version | cut -d" " -f9 | tr -d "\n"` ;
2016-08-14 16:22:25 +05:30
$ ROCM_PATH = $ ENV { 'ROCM_PATH' } // "/opt/rocm" ;
2016-04-15 16:20:35 +05:30
2016-07-21 16:02:51 +05:30
$ HIP_ATP_MARKER = $ ENV { 'HIP_ATP_MARKER' } ;
2016-08-03 09:08:40 +05:30
$ marker_path = "$ROCM_PATH/profiler/CXLActivityLogger" ;
2016-07-21 16:02:51 +05:30
2016-08-14 16:22:25 +05:30
$ ROCM_TARGET = $ ENV { 'ROCM_TARGET' } // "fiji" ;
2016-07-15 10:08:27 +05:30
2016-01-26 20:14:33 -06:00
# HCC* may be used to compile src/hip_hcc.o (and also feed the HIPCXXFLAGS below)
$ HCC = "$HCC_HOME/bin/hcc" ;
2016-04-11 13:04:13 -05:00
$ HCCFLAGS = "-hc -I$HCC_HOME/include " ;
2016-01-26 20:14:33 -06:00
$ HIPCC = $ HCC ;
$ HIPCXXFLAGS = $ HCCFLAGS ;
2016-04-28 13:17:49 -05:00
2016-01-26 20:14:33 -06:00
$ HIPCXXFLAGS . = " -I$HIP_PATH/include/hcc_detail/cuda" ;
2016-03-23 12:59:52 -05:00
$ HIPCXXFLAGS . = " -I$HSA_PATH/include" ;
2016-07-25 10:15:02 -05:00
$ HIPCXXFLAGS . = " -Wno-deprecated-register" ;
2016-07-13 11:26:03 +05:30
$ HIPLDFLAGS = "-hc -L$HCC_HOME/lib -Wl,--rpath=$HCC_HOME/lib -lc++ -ldl -lpthread -Wl,--whole-archive -lmcwamp -Wl,--no-whole-archive" ;
2016-04-02 22:32:05 +05:30
# Suppress linker warnings in case HCC distribution contains OpenCL/SPIR symbols
2016-07-15 10:40:56 +05:30
$ HOST_OSNAME = `cat /etc/os-release | grep "^ID\=" | cut -d= -f2 | tr -d '\n'` ;
$ HOST_OSVER = `cat /etc/os-release | grep "^VERSION_ID\=" | cut -d= -f2 | tr -d '\n'` ;
if ( $ HOST_OSNAME eq "ubuntu" and $ HOST_OSVER eq "\"16.04\"" ) {
# No additional flags required
} else {
$ HIPLDFLAGS . = " -Wl,--defsym=_binary_kernel_spir_end=0 -Wl,--defsym=_binary_kernel_spir_start=0 -Wl,--defsym=_binary_kernel_cl_start=0 -Wl,--defsym=_binary_kernel_cl_end=0" ;
}
2016-07-13 11:26:03 +05:30
2016-04-02 22:32:05 +05:30
# Satisfy HCC dependencies
2016-08-26 10:35:30 +05:30
$ HIPLDFLAGS . = " -lc++abi -lsupc++" ;
2016-07-13 11:26:03 +05:30
$ HIPLDFLAGS . = " -L$HSA_PATH/lib -L$ROCM_PATH/lib -lhsa-runtime64 -lhc_am -lhsakmt" ;
2016-03-23 01:17:53 -05:00
2016-07-15 10:08:27 +05:30
# Handle ROCm target platform
if ( $ ROCM_TARGET eq "fiji" ) {
$ HIPLDFLAGS . = " -amdgpu-target=AMD:AMDGPU:8:0:3" ;
}
2016-08-14 16:22:25 +05:30
if ( $ ROCM_TARGET eq "carrizo" ) {
$ HIPLDFLAGS . = " -amdgpu-target=AMD:AMDGPU:8:0:1" ;
}
2016-07-15 10:08:27 +05:30
if ( $ ROCM_TARGET eq "hawaii" ) {
$ HIPLDFLAGS . = " -amdgpu-target=AMD:AMDGPU:7:0:1" ;
}
2016-03-23 01:17:53 -05:00
# Add trace marker library:
2016-03-29 17:26:44 -05:00
# TODO - once we cleanly separate the HIP API headers from HIP library headers this logic should move to CMakebuild option - apps do not need to see the marker library.
2016-07-21 16:02:51 +05:30
if ( $ HIP_ATP_MARKER ) {
$ marker_inc_path = "$marker_path/include" ;
if ( - e $ marker_inc_path ) {
$ HIPCXXFLAGS . = " -I$marker_inc_path" ;
}
2016-08-03 09:08:40 +05:30
}
2016-07-21 16:02:51 +05:30
2016-08-03 09:08:40 +05:30
$ marker_lib_path = "$marker_path/bin/x86_64" ;
if ( - e $ marker_lib_path ) {
$ HIPLDFLAGS . = " -L$marker_lib_path -lCXLActivityLogger -Wl,--rpath=$marker_lib_path" ;
2016-03-22 09:27:10 -05:00
}
2016-03-23 01:17:53 -05:00
2016-07-13 11:26:03 +05:30
# Add C++ libs for GCC.
$ HIPLDFLAGS . = " -lstdc++" ;
$ HIPLDFLAGS . = " -lm" ;
2016-01-26 20:14:33 -06:00
if ( $ verbose & 0x2 ) {
print ( "HSA_PATH=$HSA_PATH\n" ) ;
print ( "HCC_HOME=$HCC_HOME\n" ) ;
}
} elsif ( $ HIP_PLATFORM eq "nvcc" ) {
2016-05-02 11:33:22 -05:00
if ( $ verbose & 0x2 ) {
print ( "CUDA_PATH=$CUDA_PATH\n" ) ;
}
2016-08-14 16:22:25 +05:30
$ CUDA_PATH = $ ENV { 'CUDA_PATH' } // '/usr/local/cuda' ;
2016-01-26 20:14:33 -06:00
$ HIPCC = "$CUDA_PATH/bin/nvcc" ;
$ HIPCXXFLAGS . = " -I$CUDA_PATH/include" ;
2016-08-29 15:05:12 -05:00
$ HIPLDFLAGS = "-lcuda -lcudart" ;
2016-01-26 20:14:33 -06:00
} else {
2016-07-13 11:26:03 +05:30
printf ( "error: unknown HIP_PLATFORM = '$HIP_PLATFORM'" ) ;
exit ( - 1 ) ;
2016-01-26 20:14:33 -06:00
}
2016-09-01 15:06:36 +05:30
# Add paths to common HIP includes:
$ HIPCXXFLAGS . = " -I$HIP_PATH/include" ;
my $ compileOnly = 0 ;
my $ needCXXFLAGS = 0 ; # need to add CXX flags to compile step
my $ needLDFLAGS = 1 ; # need to add LDFLAGS to compile step.
my $ hasC = 0 ; # options contain a c-style file (NVCC must force recognition as GPU file)
my $ hasCU = 0 ; # options contain a cu-style file (HCC must force recognition as GPU file)
my $ needHipHcc = ( $ HIP_PLATFORM eq 'hcc' ) ; # set if we need to link hip_hcc.o from src tree. (some builds, ie cmake, provide their own)
my $ printHipVersion = 0 ; # print HIP version
my $ runCmd = 1 ;
2016-09-02 15:07:33 +05:30
my $ buildDeps = 0 ;
2016-09-01 15:06:36 +05:30
my @ options = ( ) ;
my @ inputs = ( ) ;
if ( $ verbose & 0x4 ) {
print "hipcc-args: " , join ( " " , @ ARGV ) , "\n" ;
}
2016-08-31 20:36:36 -05:00
2016-09-01 15:06:36 +05:30
# Handle code object generation
my $ ISACMD = "" ;
2016-08-31 20:36:36 -05:00
if ( $ HIP_PLATFORM eq "hcc" ) {
2016-09-07 10:23:02 +05:30
$ ISACMD . = "set ROCM_PATH=$ROCM_PATH && set ROCM_TARGET=$ROCM_TARGET && $HIP_PATH/bin/hccgenco.sh " ;
2016-09-01 10:39:14 -05:00
if ( $ ARGV [ 0 ] eq "--genco" ) {
2016-09-01 15:06:36 +05:30
foreach $ isaarg ( @ ARGV [ 1 .. $# ARGV ] ) {
2016-08-31 20:36:36 -05:00
$ ISACMD . = " " ;
$ ISACMD . = $ isaarg ;
}
2016-09-01 15:06:36 +05:30
if ( $ verbose & 0x1 ) {
print "hipcc-cmd: " , $ ISACMD , "\n" ;
}
system ( $ ISACMD ) and die ( ) ;
2016-08-31 20:36:36 -05:00
exit ( 0 ) ;
}
}
if ( $ HIP_PLATFORM eq "nvcc" ) {
2016-09-01 15:06:36 +05:30
$ ISACMD . = "$HIP_PATH/bin/hipcc -ptx " ;
2016-09-01 10:39:14 -05:00
if ( $ ARGV [ 0 ] eq "--genco" ) {
2016-09-01 15:06:36 +05:30
foreach $ isaarg ( @ ARGV [ 1 .. $# ARGV ] ) {
2016-08-31 20:36:36 -05:00
$ ISACMD . = " " ;
2016-09-01 12:11:11 +05:30
$ ISACMD . = $ isaarg ;
2016-08-31 20:36:36 -05:00
}
2016-09-01 15:06:36 +05:30
if ( $ verbose & 0x1 ) {
print "hipcc-cmd: " , $ ISACMD , "\n" ;
}
system ( $ ISACMD ) and die ( ) ;
2016-08-31 20:36:36 -05:00
exit ( 0 ) ;
2016-08-31 13:05:57 -05:00
}
}
2016-01-26 20:14:33 -06:00
2016-03-24 11:53:28 -05:00
my $ toolArgs = "" ; # arguments to pass to the hcc or nvcc tool
2016-08-31 13:05:57 -05:00
2016-07-13 11:26:03 +05:30
foreach $ arg ( @ ARGV )
2016-01-26 20:14:33 -06:00
{
2016-03-24 11:53:28 -05:00
my $ swallowArg = 0 ;
2016-01-26 20:14:33 -06:00
if ( $ arg eq '-c' ) {
$ compileOnly = 1 ;
$ needCXXFLAGS = 1 ;
$ needLDFLAGS = 0 ;
}
if ( $ arg eq '-o' ) {
$ needLDFLAGS = 1 ;
}
2016-05-02 23:47:04 -05:00
if ( $ arg eq '-stdlib=libc++' and $ setStdLib eq 0 )
2016-04-06 14:18:51 -05:00
{
2016-04-28 13:17:49 -05:00
$ HIPCXXFLAGS . = " -stdlib=libc++" ;
2016-05-02 23:47:04 -05:00
$ setStdLib = 1 ;
}
if ( $ arg eq '-stdlib=libstdc++' and $ setStdLib eq 0 )
{
$ HIPCXXFLAGS . = " -stdlib=libstdc++" ;
$ setStdLib = 1 ;
2016-04-06 14:18:51 -05:00
}
2016-06-14 14:51:03 +05:30
if ( $ arg eq '--version' ) {
$ printHipVersion = 1 ;
}
if ( $ arg eq '--short-version' ) {
$ printHipVersion = 1 ;
$ runCmd = 0 ;
}
2016-09-02 15:07:33 +05:30
if ( $ arg eq '-M' ) {
$ compileOnly = 1 ;
$ buildDeps = 1 ;
}
2016-01-26 20:14:33 -06:00
if ( $ arg =~ m/^-/ ) {
# options start with -
2016-07-13 11:26:03 +05:30
2016-03-24 11:53:28 -05:00
# Process HIPCC options here:
if ( $ arg =~ m/^--hipcc/ ) {
$ swallowArg = 1 ;
if ( $ arg eq "--hipcc_explicit_lib" ) {
# Some environments (ie cmake tests) already link their own hip_hcc.o, so don't add here:
$ needHipHcc = 0 ;
}
} else {
push ( @ options , $ arg ) ;
}
2016-01-26 20:14:33 -06:00
#print "O: <$arg>\n";
} else {
2016-07-13 11:26:03 +05:30
# input files and libraries
2016-03-03 09:47:37 +05:30
if ( ( $ arg =~ /\.cpp$/ ) or ( $ arg =~ /\.c$/ ) or ( $ arg =~ /\.cc$/ ) ) {
2016-01-26 20:14:33 -06:00
$ hasC = 1 ;
$ needCXXFLAGS = 1 ;
2016-07-13 11:26:03 +05:30
}
2016-03-03 09:47:37 +05:30
if ( ( $ arg =~ /\.cu$/ ) or ( $ arg =~ /\.cuh$/ ) ) {
2016-01-26 20:14:33 -06:00
$ hasCU = 1 ;
$ needCXXFLAGS = 1 ;
}
push ( @ inputs , $ arg ) ;
#print "I: <$arg>\n";
}
2016-03-24 11:53:28 -05:00
$ toolArgs . = " $arg" unless $ swallowArg ;
2016-01-26 20:14:33 -06:00
}
if ( $ hasC and $ HIP_PLATFORM eq 'nvcc' ) {
$ HIPCXXFLAGS . = " -x cu" ;
}
if ( $ hasCU and $ HIP_PLATFORM eq 'hcc' ) {
$ HIPCXXFLAGS . = " -x c++" ;
}
2016-09-02 15:07:33 +05:30
if ( $ buildDeps and $ HIP_PLATFORM eq 'nvcc' ) {
$ HIPCXXFLAGS . = " -M -D__CUDACC__" ;
}
2016-01-26 20:14:33 -06:00
2016-05-02 23:47:04 -05:00
if ( $ setStdLib eq 0 and $ HIP_PLATFORM eq 'hcc' )
2016-04-06 14:50:27 -05:00
{
2016-05-03 11:14:27 -05:00
$ HIPCXXFLAGS . = " -stdlib=libstdc++" ;
2016-04-06 14:50:27 -05:00
}
2016-01-26 20:14:33 -06:00
if ( $ needHipHcc ) {
2016-08-19 13:07:22 +05:30
$ HIP_LIB_TYPE = $ hipConfig { 'HIP_LIB_TYPE' } // 0 ;
2016-04-01 16:08:49 +05:30
2016-08-19 13:07:22 +05:30
if ( $ HIP_LIB_TYPE eq 0 ) {
2016-08-16 14:36:25 -05:00
$ HIPLDFLAGS . = " $HIP_PATH/lib/device_util.cpp.o $HIP_PATH/lib/hip_device.cpp.o $HIP_PATH/lib/hip_error.cpp.o $HIP_PATH/lib/hip_event.cpp.o $HIP_PATH/lib/hip_hcc.cpp.o $HIP_PATH/lib/hip_memory.cpp.o $HIP_PATH/lib/hip_peer.cpp.o $HIP_PATH/lib/hip_stream.cpp.o $HIP_PATH/lib/unpinned_copy_engine.cpp.o $HIP_PATH/lib/hip_ldg.cpp.o $HIP_PATH/lib/hip_fp16.cpp.o $HIP_PATH/lib/hip_context.cpp.o $HIP_PATH/lib/hip_module.cpp.o" ;
2016-08-19 13:07:22 +05:30
} elsif ( $ HIP_LIB_TYPE eq 1 ) {
$ HIPLDFLAGS . = " -L$HIP_PATH/lib -lhip_hcc" ;
} else {
$ HIPLDFLAGS . = " -L$HIP_PATH/lib -Wl,--rpath=$HIP_PATH/lib -lhip_hcc" ;
2016-04-01 16:08:49 +05:30
}
2016-01-26 20:14:33 -06:00
}
# hipcc currrently requires separate compilation of source files, ie it is not possible to pass
# CPP files combined with .O files
2016-07-13 11:26:03 +05:30
# Reason is that NVCC uses the file extension to determine whether to compile in CUDA mode or
2016-01-26 20:14:33 -06:00
# pass-through CPP mode.
my $ CMD = "$HIPCC" ;
if ( $ needCXXFLAGS ) {
$ CMD . = " $HIPCXXFLAGS" ;
2016-07-13 11:26:03 +05:30
}
2016-01-26 20:14:33 -06:00
if ( $ needLDFLAGS and not $ compileOnly ) {
$ CMD . = " $HIPLDFLAGS" ;
}
2016-03-24 11:53:28 -05:00
$ CMD . = " $toolArgs" ;
2016-01-26 20:14:33 -06:00
if ( $ verbose & 0x1 ) {
print "hipcc-cmd: " , $ CMD , "\n" ;
}
2016-06-14 14:51:03 +05:30
if ( $ printHipVersion ) {
if ( $ runCmd ) {
print "HIP version: "
}
2016-07-11 16:38:41 +05:30
print $ HIP_VERSION , "\n" ;
2016-06-14 14:51:03 +05:30
}
if ( $ runCmd ) {
2016-08-14 16:22:25 +05:30
if ( $ HIP_PLATFORM eq "hcc" and exists ( $ hipConfig { 'HCC_VERSION' } ) and $ HCC_VERSION ne $ hipConfig { 'HCC_VERSION' } ) {
2016-08-03 11:32:08 +05:30
print ( "HIP was built using $hipConfig{'HCC_VERSION'}, but you are using $HCC_VERSION. Please rebuild HIP.\n" ) && die ( ) ;
}
2016-06-14 14:51:03 +05:30
system ( "$CMD" ) and die ( ) ;
}